package model;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import utils.SimpleText;

public class BlogPost {
	public static String[] labels = { "UNKNOWN", "NEUTRAL", "NEGATIVE",
			"MIXED", "POSITIVE" };// By default the label is "UNKNOWN"

	public static final int UNKNOWN = 0;
	public static final int IRRELEVANT = 0;
	public static final int RELEVANT = 1;
	public static final int NEUTRAL = 1;
	public static final int NEGATIVE = 2;
	public static final int MIXED = 3;
	public static final int POSITIVE = 4;
	private int sentimentPolarityLabel = UNKNOWN;
	private int topicalityLabel = UNKNOWN;
	private String id;
	private Vector<Sentence> sentences;

	public BlogPost(String id, Vector<Sentence> sentences) {
		this.id = id;
		this.sentences = sentences;
	}

	public BlogPost(String fileString, String text) {
		parse(fileString);
		sentences = new Vector<Sentence>();
		for (String sentence : SimpleText.toSentences(text)) {
			sentences.add(new Sentence(sentence));
		}
	}

	public String toString() {
		String postStr = "";
		for (Sentence s : sentences) {
			postStr = postStr.concat(s.getContent() + " | ");
		}
		return postStr;
	}

	public Vector<Sentence> getSentences() {
		return sentences;
	}

	public String toAnnotation() {
		String annotated = "";
		for (Sentence s : sentences) {
			annotated = annotated.concat(s.toAnnotation() + "\n");
		}
		return annotated;
	}

	public String getTopical() {
		String topical = "";
		for (Sentence s : sentences) {
			if (s.getSentimentPolarity() != Sentence.UNKNOWN) {
				topical = topical.concat(s.getContent() + "\n");
			}
		}
		return topical;
	}

	public String getID() {
		return id;
	}

	// A helper method to parse the file name to identify the label
	private void parse(String fileName) {
		// BLOG06-20060201-015-0000703125__2.txt
		String regex = "(BLOG\\d{2}-\\d{8}-\\d{3}-\\d{10})__(\\d)\\.txt";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(fileName);
		if (matcher.find()) {
			id = (matcher.group(1));
			sentimentPolarityLabel = Integer.parseInt(matcher.group(2));
		}
	}

	public String writeToDisk(String directory) {
		String message = "";
		if (System.getProperty("os.name").contains("Windows")) {
			directory = directory.concat("\\");
		} else {
			directory = directory.concat("/");
		}
		if (getTopical().length() != 0) {
			SimpleText.saveToFile(
					toAnnotation(),
					directory.concat(id).concat("__" + topicalityLabel)
							.concat(".manual.sum"));
			SimpleText.saveToFile(
					getContent(),
					directory.concat(id).concat("__" + topicalityLabel)
							.concat(".orig.txt"));
			message = message.concat(id + " saved to " + directory + "\n");
		} else {
			message = message.concat("Ignoring empty file : " + id + "\n");
		}
		return message;
	}

	private String getContent() {
		String content = "";
		for (Sentence s : sentences) {
			content = content.concat(s.getContent() + "\n");
		}
		return content;
	}

	public String writeToDB(Connection conn, String annotator) {
		String message = "";
		Statement statement;
		try {
			statement = conn.createStatement();

			int index = 0;
			for (Sentence s : sentences) {
				// If label exists, update them, else insert a new row
				if (statement.executeQuery(
						"select * from labels where blog_id = '" + id
								+ "' and sequence = " + index
								+ " and annotator = '" + annotator + "'")
						.next()) {
					System.err.println("Updating existing label for sentence "
							+ index);
					Statement updateStatement = conn.createStatement();
					System.out.println(updateStatement
							.executeUpdate("update labels set topicality = "
									+ s.getTopicality()
									+ ", sentiment_polarity = "
									+ s.getSentimentPolarity()
									+ " where blog_id = '" + id
									+ "' and sequence = " + index
									+ " and annotator = '" + annotator + "'")
							+ " records affected.");
					updateStatement.close();
				} else {
					System.err.println("Creating new label for sentence "
							+ index);
					PreparedStatement insertStatement = conn
							.prepareStatement("insert into labels (blog_id, sequence, annotator, topicality,"
									+ " sentiment_polarity) values (?,?,?,?,?)");
					// If label doesn't exist, create them
					insertStatement.setString(1, id);
					insertStatement.setString(2, Integer.toString(index));
					insertStatement.setString(3, annotator);
					insertStatement.setString(4,
							Integer.toString(s.getTopicality()));
					insertStatement.setString(5,
							Integer.toString(s.getSentimentPolarity()));
					System.out.println(insertStatement.executeUpdate()
							+ " records affected.");
					insertStatement.close();
				}
				index++;
			}

			// Update the blog labels
			System.err.println("Updating post labels");
			/**
			 * TODO similar to the way sentences are processed, need to check
			 * whether the post labels exists first. However we currently do not
			 * allow post level annotation, therefore not implemented yet.
			 */

			System.out.println(statement
					.executeUpdate("update post set topicality = "
							+ topicalityLabel + ", sentiment_polarity = "
							+ sentimentPolarityLabel + " where id = '" + id
							+ "'" + " and annotator = '" + annotator + "'")
					+ " records affected.");

			message = message.concat(id + " updated\n");
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return message;
	}

	public String upload(Connection conn, String topic) {
		String message = "";

		PreparedStatement statement1 = null;

		try {
			statement1 = conn
					.prepareStatement("insert into sentences (blog_id, sequence, content) values (?,?,?)");
			System.out.println(id + " : " + topic + " : " + topicalityLabel
					+ " : " + sentimentPolarityLabel);
			// Upload the sentences
			int index = 0;
			for (Sentence s : sentences) {
				System.out.print(index + " ");
				statement1.setString(1, id);
				statement1.setString(2, Integer.toString(index));
				statement1.setString(3, s.getContent());
				statement1.executeUpdate();
				index++;
			}
			System.out.println();
			statement1.close();

			// Upload the blog
			statement1 = conn
					.prepareStatement("insert into post (id, topic_no, topicality, sentiment_polarity, annotator) values (?,?,?,?,?)");
			statement1.setString(1, id);
			statement1.setString(2, topic);
			statement1.setString(3, Integer.toString(topicalityLabel));
			statement1.setString(4, Integer.toString(sentimentPolarityLabel));
			statement1.setString(5, "TREC");
			statement1.executeUpdate();

			message = message.concat(id + " uploaded\n");

		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return message;

	}

	public int getTopicalityLabel() {
		return topicalityLabel;
	}

	public int getSentimentPolarityLabel() {
		return sentimentPolarityLabel;
	}

	public void setTopicality(int topicality) {
		this.topicalityLabel = topicality;
	}

	public void setSentimentPolarityLabel(int sentimentPolarityLabel) {
		this.sentimentPolarityLabel = sentimentPolarityLabel;
	}

	public int getNumOfSentencesByLabel(int label) {
		int count = 0;
		for (Sentence s : sentences) {
			if (s.getSentimentPolarity() == label) {
				count++;
			}
		}
		return count;
	}

	public int getLenOfSentencesByLabel(int label) {
		int count = 0;
		for (Sentence s : sentences) {
			if (s.getSentimentPolarity() == label) {
				count += s.getContent().length();
			}
		}
		return count;
	}

	public int getNumOfToksOfSentencesByLabel(int label) {
		int count = 0;
		for (Sentence s : sentences) {
			if (s.getSentimentPolarity() == label) {
				count += s.getNumOfTokens();
			}
		}
		return count;
	}

	public double getDriftingnessBySentence() {
		return (double) getNumOfSentencesByLabel(Sentence.IRRELEVANT)
				/ sentences.size();
	}

	public double getDriftingnessByLength() {
		int driftingLength = 0, topicalLength = 0;
		for (Sentence s : sentences) {
			if (s.getSentimentPolarity() == 0) {
				driftingLength += s.getContent().length();
			} else {
				topicalLength += s.getContent().length();
			}
		}
		return (double) driftingLength / (driftingLength + topicalLength);
	}

	public double getDriftingnessByTokens() {
		int driftingTokens = 0, topicalTokens = 0;
		for (Sentence s : sentences) {
			if (s.getSentimentPolarity() == 0) {
				driftingTokens += s.getNumOfTokens();
			} else {
				topicalTokens += s.getNumOfTokens();
			}
		}
		return (double) driftingTokens / (driftingTokens + topicalTokens);
	}

}
